home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / shllutil.lha / shellutils-1.8 / lib / strtol.c < prev    next >
C/C++ Source or Header  |  1992-10-13  |  4KB  |  182 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ctype.h>
  20. #include <errno.h>
  21.  
  22. #if HAVE_LIMITS_H
  23. #include <limits.h>
  24. #endif
  25. #ifndef ULONG_MAX
  26. #define    LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
  27. #define LONG_MIN (-LONG_MAX-1)
  28. #define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
  29. #endif
  30.  
  31. #if STDC_HEADERS
  32. #include <stddef.h>
  33. #include <stdlib.h>
  34. #else
  35. #define NULL 0
  36. extern int errno;
  37. #endif
  38.  
  39. #if !__STDC__
  40. #define const
  41. #endif
  42.  
  43. #ifndef    UNSIGNED
  44. #define    UNSIGNED    0
  45. #endif
  46.  
  47. /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  48.    If BASE is 0 the base is determined by the presence of a leading
  49.    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  50.    If BASE is < 2 or > 36, it is reset to 10.
  51.    If ENDPTR is not NULL, a pointer to the character after the last
  52.    one converted is stored in *ENDPTR.  */
  53. #if    UNSIGNED
  54. unsigned long int
  55. #define    strtol    strtoul
  56. #else
  57. long int
  58. #endif
  59. strtol (nptr, endptr, base)
  60.      const char *nptr;
  61.      char **endptr;
  62.      int base;
  63. {
  64.   int negative;
  65.   register unsigned long int cutoff;
  66.   register unsigned int cutlim;
  67.   register unsigned long int i;
  68.   register const char *s;
  69.   register unsigned char c;
  70.   const char *save;
  71.   int overflow;
  72.  
  73.   if (base < 0 || base == 1 || base > 36)
  74.     base = 10;
  75.  
  76.   s = nptr;
  77.  
  78.   /* Skip white space.  */
  79.   while (isspace (*s))
  80.     ++s;
  81.   if (*s == '\0')
  82.     goto noconv;
  83.  
  84.   /* Check for a sign.  */
  85.   if (*s == '-')
  86.     {
  87.       negative = 1;
  88.       ++s;
  89.     }
  90.   else if (*s == '+')
  91.     {
  92.       negative = 0;
  93.       ++s;
  94.     }
  95.   else
  96.     negative = 0;
  97.  
  98.   if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
  99.     s += 2;
  100.  
  101.   /* If BASE is zero, figure it out ourselves.  */
  102.   if (base == 0)
  103.     {
  104.       if (*s == '0')
  105.     {
  106.       if (toupper (s[1]) == 'X')
  107.         {
  108.           s += 2;
  109.           base = 16;
  110.         }
  111.       else
  112.         base = 8;
  113.     }
  114.       else
  115.     base = 10;
  116.     }
  117.  
  118.   /* Save the pointer so we can check later if anything happened.  */
  119.   save = s;
  120.  
  121.   cutoff = ULONG_MAX / (unsigned long int) base;
  122.   cutlim = ULONG_MAX % (unsigned long int) base;
  123.  
  124.   overflow = 0;
  125.   i = 0;
  126.   for (c = *s; c != '\0'; c = *++s)
  127.     {
  128.       if (isdigit (c))
  129.     c -= '0';
  130.       else if (isalpha (c))
  131.     c = toupper (c) - 'A' + 10;
  132.       else
  133.     break;
  134.       if (c >= base)
  135.     break;
  136.       /* Check for overflow.  */
  137.       if (i > cutoff || (i == cutoff && c > cutlim))
  138.     overflow = 1;
  139.       else
  140.     {
  141.       i *= (unsigned long int) base;
  142.       i += c;
  143.     }
  144.     }
  145.  
  146.   /* Check if anything actually happened.  */
  147.   if (s == save)
  148.     goto noconv;
  149.  
  150.   /* Store in ENDPTR the address of one character
  151.      past the last character we converted.  */
  152.   if (endptr != NULL)
  153.     *endptr = (char *) s;
  154.  
  155. #if    !UNSIGNED
  156.   /* Check for a value that is within the range of
  157.      `unsigned long int', but outside the range of `long int'.  */
  158.   if (i > (negative ?
  159.        - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
  160.     overflow = 1;
  161. #endif
  162.  
  163.   if (overflow)
  164.     {
  165.       errno = ERANGE;
  166. #if    UNSIGNED
  167.       return ULONG_MAX;
  168. #else
  169.       return negative ? LONG_MIN : LONG_MAX;
  170. #endif
  171.     }
  172.  
  173.   /* Return the result of the appropriate sign.  */
  174.   return (negative ? - i : i);
  175.  
  176. noconv:;
  177.   /* There was no number to convert.  */
  178.   if (endptr != NULL)
  179.     *endptr = (char *) nptr;
  180.   return 0L;
  181. }
  182.